home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume8 / comsat.s5 < prev    next >
Encoding:
Text File  |  1989-08-24  |  22.1 KB  |  881 lines

  1. Newsgroups: comp.sources.misc
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. subject: v08i015: comsat and biff for System V with a FIFO
  4. Reply-To: edf@ROCKY2.ROCKEFELLER.EDU (David MacKenzie)
  5.  
  6. Posting-number: Volume 8, Issue 15
  7. Submitted-by: edf@ROCKY2.ROCKEFELLER.EDU (David MacKenzie)
  8. Archive-name: comsat.s5
  9.  
  10. This is a port of the free comsat program from the 4.3BSD-tahoe release
  11. to System V, with a FIFO (named pipe) replacing sockets.
  12.  
  13. When a new mail message is delivered, the local mail delivery agent
  14. writes a message to a FIFO, which the comsat daemon reads.  If the
  15. recipient of the mail is logged in and `biff y' (similar to mesg y but a
  16. different bit of the tty is used), a message is printed on the user's
  17. screen summarizing the new mail.
  18.  
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of shell archive."
  27. # Contents:  README comsat.c biff.c lmail.diffs mailwrap.c
  28. # Wrapped by dave@edfdc on Wed Aug 23 01:34:53 1989
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'README' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'README'\"
  32. else
  33. echo shar: Extracting \"'README'\" \(1518 characters\)
  34. sed "s/^X//" >'README' <<'END_OF_FILE'
  35. XThis is a port of the free comsat program from the 4.3BSD-tahoe release
  36. Xto System V, with a FIFO (named pipe) replacing sockets.
  37. X
  38. XWhen a new mail message is delivered, the local mail delivery agent
  39. Xwrites a message (for the format, see the comment at the top of
  40. Xcomsat.c) to a FIFO, which the comsat daemon reads.  If the recipient
  41. Xof the mail is logged in and `biff y' (similar to mesg y but a
  42. Xdifferent bit of the tty is used), a message is printed on the user's
  43. Xscreen summarizing the new mail.
  44. X
  45. XFiles included in this package:
  46. X
  47. XREADME        This file.
  48. Xcomsat.c    Daemon that prints the biff messages.
  49. Xbiff.c        Allow/prevent receipt of biff messages.
  50. Xlmail.diffs    Diffs to lmail from comp.sources.misc volume 4, a local
  51. X        mail delivery program for smail 2.5, to make it write a
  52. X        message to the comsat FIFO when new mail is delivered.
  53. Xmailwrap.c    An alternative approach to using lmail; a program to
  54. X        write a message to the comsat FIFO, then run your old,
  55. X        renamed local mail delivery program.
  56. X        Written by Jim Mattson <mattson%cs@ucsd.edu>.
  57. X
  58. XFollowing is a list of the main portability issues I encountered while
  59. Xporting comsat from 4.3BSD to System V.  In addition to these, I added
  60. Xmore comments and gave some identifiers more descriptive names, and ran
  61. Xthe file through GNU indent.
  62. X
  63. Xsignals
  64. Xsockets vs. FIFO
  65. Xinvocation and exit
  66. Xerror logging
  67. Xindex vs. strchr
  68. Xsgtty vs. termio
  69. Xgethostname vs. uname
  70. Xfailure of interrupted system calls (fgets seems to handle this correctly)
  71. X
  72. XDavid MacKenzie
  73. X<edf@rocky2.rockefeller.edu>
  74. END_OF_FILE
  75. if test 1518 -ne `wc -c <'README'`; then
  76.     echo shar: \"'README'\" unpacked with wrong size!
  77. fi
  78. # end of 'README'
  79. fi
  80. if test -f 'comsat.c' -a "${1}" != "-c" ; then 
  81.   echo shar: Will not clobber existing file \"'comsat.c'\"
  82. else
  83. echo shar: Extracting \"'comsat.c'\" \(11659 characters\)
  84. sed "s/^X//" >'comsat.c' <<'END_OF_FILE'
  85. X/*
  86. X * Copyright (c) 1980 Regents of the University of California.
  87. X * All rights reserved.
  88. X *
  89. X * Redistribution and use in source and binary forms are permitted
  90. X * provided that the above copyright notice and this paragraph are
  91. X * duplicated in all such forms and that any documentation,
  92. X * advertising materials, and other materials related to such
  93. X * distribution and use acknowledge that the software was developed
  94. X * by the University of California, Berkeley.  The name of the
  95. X * University may not be used to endorse or promote products derived
  96. X * from this software without specific prior written permission.
  97. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  98. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  99. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  100. X */
  101. X
  102. X#ifndef lint
  103. Xchar copyright[] =
  104. X"@(#) Copyright (c) 1980 Regents of the University of California.\n\
  105. X All rights reserved.\n";
  106. X#endif /* not lint */
  107. X
  108. X/* comsat - daemon to notify registered users of new mail
  109. X   Usage: comsat 2> /tmp/comsat.errors
  110. X
  111. X   Receives one line messages of the form
  112. X   user@mailbox-offset\n
  113. X   on a named pipe, and if the user is logged on and "biff y" (owner
  114. X   execute bit of tty is turned on), prints a message summarizing the new
  115. X   mail on the user's screen.
  116. X
  117. X   Converted for System V with FIFO
  118. X   by David MacKenzie <edf@rocky2.rockefeller.edu>
  119. X   with additional changes
  120. X   by Jim Mattson <mattson%cs@ucsd.edu>
  121. X
  122. X   Latest revision: 08/23/89 */
  123. X
  124. X#include <stdio.h>
  125. X#include <sys/types.h>
  126. X#include <sys/stat.h>
  127. X#include <utmp.h>
  128. X#include <signal.h>
  129. X#include <errno.h>
  130. X#include <fcntl.h>
  131. X#include <termio.h>
  132. X#include <string.h>
  133. X#include <varargs.h>
  134. X#include <sys/utsname.h>
  135. X
  136. X/* BSD-compatible constants for lseek. */
  137. X#define L_SET 0
  138. X#define L_INCR 1
  139. X#define L_XTND 2
  140. X
  141. X/* The directory where system mailboxes are located. */
  142. X#define SYSMAILDIR "/usr/mail"
  143. X
  144. X/* Path of the named pipe used to send messages to this program. */
  145. X#define FIFO "/etc/comsat.fifo"
  146. X
  147. X/* The number of seconds between checks of the utmp. */
  148. X#define ALARM_INTERVAL 15
  149. X
  150. X/* If this is defined, no blank line will be printed between the
  151. X   header lines (e.g., "Subject:") and the head of the message text.
  152. X   The blank line is present in the 4.3BSD comsat but absent in the
  153. X   4.3BSD-tahoe comsat from which this version is derived. */
  154. X/* #define JOIN_HEADER_AND_TEXT */
  155. X
  156. Xchar *malloc ();
  157. Xchar *realloc ();
  158. Xoff_t atol ();
  159. Xoff_t fseek ();
  160. Xoff_t lseek ();
  161. Xtime_t time ();
  162. X
  163. Xchar *xmalloc ();
  164. Xchar *xrealloc ();
  165. Xint read_utmp ();
  166. Xint note_alarm ();
  167. Xvoid mail_for ();
  168. Xvoid msg_perror_fatal ();
  169. Xvoid notify ();
  170. Xvoid summarize_new_mail ();
  171. X
  172. X/* This machine's host name, used in the notification message. */
  173. Xchar hostname[10];
  174. X
  175. X/* Contents of the utmp. */
  176. Xstruct utmp *utmp;
  177. X
  178. X/* If nonzero, the alarm rang while sending a biff message. */
  179. Xint alarm_rang;
  180. X
  181. X/* Number of entries in `utmp'. */
  182. Xint nutmp;
  183. X
  184. X/* File descriptor for reading the utmp. */
  185. Xint utfd;
  186. X
  187. X/* The name this program was run with, for error messages. */
  188. Xchar *program_name;
  189. X
  190. X/* ARGSUSED */
  191. Xint
  192. Xmain (argc, argv)
  193. X     int argc;
  194. X     char **argv;
  195. X{
  196. X  FILE *fifp;
  197. X  char msgbuf[100];
  198. X
  199. X  program_name = argv[0];
  200. X
  201. X  signal (SIGINT, SIG_IGN);
  202. X  signal (SIGHUP, SIG_IGN);
  203. X
  204. X  /* Don't tie up a filesystem. */
  205. X  if (chdir ("/") == -1)
  206. X    msg_perror_fatal ("Cannot chdir to /");
  207. X
  208. X  if (daemon_running (FIFO))
  209. X    {
  210. X      fprintf (stderr, "%s: Daemon is already running\n", program_name);
  211. X      exit (1);
  212. X    }
  213. X  switch (fork ())
  214. X    {
  215. X    case -1:
  216. X      msg_perror_fatal ("Cannot fork");
  217. X    case 0:            /* Child. */
  218. X      break;
  219. X    default:            /* Parent. */
  220. X      _exit (0);
  221. X    }
  222. X
  223. X  fclose (stdin);        /* Don't need these anymore. */
  224. X  fclose (stdout);
  225. X  setpgrp ();            /* Detach from parent's process group. */
  226. X
  227. X  fifp = fdopen (open_fifo (FIFO), "r");
  228. X  if (fifp == NULL)
  229. X    msg_perror_fatal ("Cannot fdopen FIFO %s", FIFO);
  230. X
  231. X  utfd = open (UTMP_FILE, O_RDONLY);
  232. X  if (utfd == -1)
  233. X    msg_perror_fatal ("Cannot read %s", UTMP_FILE);
  234. X
  235. X  utmp = NULL;
  236. X  nutmp = 0;
  237. X  gethostname (hostname, sizeof (hostname));
  238. X  signal (SIGCLD, SIG_IGN);    /* Prevent zombie process creation. */
  239. X
  240. X  read_utmp ();
  241. X
  242. X  while (1)
  243. X    {
  244. X      while (fgets (msgbuf, sizeof msgbuf, fifp) == NULL)
  245. X    sleep (1);
  246. X      if (nutmp == 0)
  247. X    continue;        /* No one has logged in yet. */
  248. X      /* Don't let automatic utmp updating corrupt the in-core copy while
  249. X         we're using it. */
  250. X      alarm_rang = 0;
  251. X      signal (SIGALRM, note_alarm);
  252. X      mail_for (msgbuf);
  253. X      /* If we missed a utmp update while biffing the user, do the
  254. X         update manually and set the alarm again. */
  255. X      if (alarm_rang)
  256. X    read_utmp ();
  257. X      else
  258. X    signal (SIGALRM, read_utmp);
  259. X    }
  260. X  /* NOTREACHED */
  261. X}
  262. X
  263. X/* SIGALRM handler for while mail_for is running. */
  264. X
  265. Xint
  266. Xnote_alarm ()
  267. X{
  268. X  alarm_rang = 1;
  269. X}
  270. X
  271. X/* Normal SIGALRM handler.  Every ALARM_INTERVAL seconds, read a current
  272. X   copy of the utmp into `utmp'. */
  273. X
  274. Xint
  275. Xread_utmp ()
  276. X{
  277. X  static unsigned utmp_size = 0;/* Bytes allocated for `utmp'. */
  278. X  static unsigned utmp_mtime = 0;    /* Last modification time of utmp. */
  279. X  struct stat stats;
  280. X
  281. X  if (fstat (utfd, &stats) == -1)
  282. X    msg_perror_fatal ("Cannot fstat utmp");
  283. X  if (stats.st_mtime > utmp_mtime)
  284. X    {
  285. X      utmp_mtime = stats.st_mtime;
  286. X      if (stats.st_size > utmp_size)
  287. X    {
  288. X      utmp_size = stats.st_size + 10 * sizeof (struct utmp);
  289. X      utmp = (struct utmp *) xrealloc ((char *) utmp, utmp_size);
  290. X    }
  291. X      if (lseek (utfd, 0L, L_SET) < 0)
  292. X    msg_perror_fatal ("Cannot seek to beginning of utmp");
  293. X      nutmp = read (utfd, utmp, (unsigned) stats.st_size);
  294. X      if (nutmp == -1)
  295. X    msg_perror_fatal ("Cannot read utmp");
  296. X      nutmp /= sizeof (struct utmp);
  297. X    }
  298. X  alarm ((unsigned) ALARM_INTERVAL);
  299. X  signal (SIGALRM, read_utmp);
  300. X}
  301. X
  302. X/* `name' has the form "user@mailbox-offset\n".  Check whether "user" is
  303. X   logged on; if so, try to notify them of the new mail. */
  304. X
  305. Xvoid
  306. Xmail_for (name)
  307. X     char *name;
  308. X{
  309. X  struct utmp *utp;
  310. X  char *cp;
  311. X  off_t offset;
  312. X
  313. X  cp = strchr (name, '@');
  314. X  if (cp == NULL)
  315. X    {
  316. X      fprintf (stderr, "%s: Invalid message: %s\n", program_name, name);
  317. X      return;
  318. X    }
  319. X  *cp++ = '\0';
  320. X  offset = atol (cp);
  321. X  utp = &utmp[nutmp];
  322. X  while (--utp >= utmp)
  323. X    {
  324. X      if (!strncmp (utp->ut_user, name, sizeof (utmp[0].ut_user)))
  325. X    notify (utp, offset);
  326. X    }
  327. X}
  328. X
  329. X/* The carriage return character needed for the terminal being notified;
  330. X   it will be the null string if the terminal driver or the terminal
  331. X   is supplying a carriage return automatically with each newline. */
  332. Xstatic char *cr;
  333. X
  334. X/* If the user described in `utp' is logged on and "biff y", notify them
  335. X   of the new mail in their system mailbox at offset `offset'. */
  336. X
  337. Xvoid
  338. Xnotify (utp, offset)
  339. X     struct utmp *utp;
  340. X     off_t offset;
  341. X{
  342. X  static char tty[20] = "/dev/";
  343. X  struct termio termio;
  344. X  FILE *tp;
  345. X  char name[sizeof (utmp[0].ut_user) + 1];
  346. X  struct stat stats;
  347. X  int i;
  348. X
  349. X  strncpy (tty + 5, utp->ut_line, sizeof (utp->ut_line));
  350. X  while ((i = stat (tty, &stats)) == -1 && errno == EINTR)
  351. X    /* Do nothing. */ ;
  352. X  if (i == -1 || !(stats.st_mode & S_IEXEC))
  353. X    return;
  354. X  switch (fork ())
  355. X    {
  356. X    case -1:
  357. X      msg_perror_fatal ("Cannot fork");
  358. X    case 0:            /* Child. */
  359. X      break;
  360. X    default:            /* Parent. */
  361. X      return;
  362. X    }
  363. X  signal (SIGALRM, SIG_DFL);
  364. X  alarm ((unsigned) 30);
  365. X  tp = fopen (tty, "w");
  366. X  if (tp == NULL)
  367. X    _exit (1);
  368. X  ioctl (fileno (tp), TCGETA, &termio);
  369. X  cr = (termio.c_oflag & OPOST) && (termio.c_oflag & ONLCR)
  370. X    || (termio.c_oflag & ONLRET) ? "" : "\r";
  371. X  strncpy (name, utp->ut_user, sizeof (utp->ut_user));
  372. X  name[sizeof (name) - 1] = '\0';
  373. X  fprintf (tp, "%s\n\007New mail for %s@%.*s\007 has arrived:%s\n----%s\n",
  374. X       cr, name, sizeof (hostname), hostname, cr, cr);
  375. X  summarize_new_mail (tp, name, offset);
  376. X  fclose (tp);
  377. X  _exit (0);
  378. X}
  379. X
  380. X/* Print the first 7 lines or 560 characters (whichever comes first) of
  381. X   the new mail message that starts at byte `offset' in the system
  382. X   mailbox for user `name' to stream `tp'.  Skip header lines other than
  383. X   From, Subject, [To, and Date]. */
  384. X
  385. Xvoid
  386. Xsummarize_new_mail (tp, name, offset)
  387. X     FILE *tp;
  388. X     char *name;
  389. X     off_t offset;
  390. X{
  391. X  char *cp;
  392. X  FILE *fi;
  393. X  int linecnt;
  394. X  int charcnt;
  395. X  int inheader;
  396. X  char line[BUFSIZ];
  397. X
  398. X  cp = xmalloc (sizeof (SYSMAILDIR) + strlen (name) + 2);
  399. X  sprintf (cp, "%s/%s", SYSMAILDIR, name);
  400. X  fi = fopen (cp, "r");
  401. X  free (cp);
  402. X  if (fi == NULL)
  403. X    return;
  404. X  if (fseek (fi, offset, L_SET))
  405. X    return;
  406. X  linecnt = 7;
  407. X  charcnt = 560;
  408. X  inheader = 1;
  409. X
  410. X  while (fgets (line, sizeof (line), fi) != NULL)
  411. X    {
  412. X      if (inheader)
  413. X    {
  414. X      if (line[0] == '\n')
  415. X        {
  416. X          inheader = 0;
  417. X#ifdef JOIN_HEADER_AND_TEXT
  418. X          continue;
  419. X#endif
  420. X        }
  421. X      else if (line[0] == ' ' || line[0] == '\t'
  422. X           || strncmp (line, "From:", 5)
  423. X           && strncmp (line, "Subject:", 8))
  424. X        /* Skip header continuation lines and non-essential header lines. */
  425. X        continue;
  426. X    }
  427. X      if (linecnt <= 0 || charcnt <= 0)
  428. X    {
  429. X      fprintf (tp, "...more...%s\n", cr);
  430. X      return;
  431. X    }
  432. X      cp = strchr (line, '\n');
  433. X      if (cp)
  434. X    *cp = '\0';
  435. X      fprintf (tp, "%s%s\n", line, cr);
  436. X      charcnt -= strlen (line);
  437. X      linecnt--;
  438. X    }
  439. X  fprintf (tp, "----%s\n", cr);
  440. X}
  441. X
  442. X/* Simulate the BSD gethostname(2) system call on System V.  */
  443. X
  444. Xint
  445. Xgethostname (name, length)
  446. X     char *name;
  447. X     int length;
  448. X{
  449. X  struct utsname uts;
  450. X
  451. X  if (uname (&uts) < 0)
  452. X    return -1;
  453. X  strncpy (name, uts.nodename, length);
  454. X  return 0;
  455. X}
  456. X
  457. Xstatic void
  458. Xmemory_out ()
  459. X{
  460. X  fprintf (stderr, "%s: Virtual memory exhausted\n", program_name);
  461. X  exit (1);
  462. X}
  463. X
  464. X/* Allocate `n' bytes of memory dynamically, with error checking.  */
  465. X
  466. Xchar *
  467. Xxmalloc (n)
  468. X     unsigned n;
  469. X{
  470. X  char *p;
  471. X
  472. X  p = malloc (n);
  473. X  if (p == 0)
  474. X    memory_out ();
  475. X  return p;
  476. X}
  477. X
  478. X/* Change the size of an allocated block of memory `p' to `n' bytes,
  479. X   with error checking.
  480. X   If `p' is NULL, run xmalloc.
  481. X   If `n' is 0, run free and return NULL.  */
  482. X
  483. Xchar *
  484. Xxrealloc (p, n)
  485. X     char *p;
  486. X     unsigned n;
  487. X{
  488. X  if (p == 0)
  489. X    return xmalloc (n);
  490. X  if (n == 0)
  491. X    {
  492. X      free (p);
  493. X      return 0;
  494. X    }
  495. X  p = realloc (p, n);
  496. X  if (p == 0)
  497. X    memory_out ();
  498. X  return p;
  499. X}
  500. X
  501. X/* ANSI C function. */
  502. X
  503. Xchar *
  504. Xstrerror (n)
  505. X     int n;
  506. X{
  507. X  extern char *sys_errlist[];
  508. X  extern int sys_nerr;
  509. X
  510. X  return n >= 0 && n < sys_nerr ? sys_errlist[n] : "Unknown error";
  511. X}
  512. X
  513. X/* Print "program_name: str_and_optional_args: perror_message" on stderr,
  514. X   then exit with error status. */
  515. X/* VARARGS */
  516. Xvoid
  517. Xmsg_perror_fatal (str, va_alist)
  518. X     char *str;
  519. X     va_dcl
  520. X{
  521. X  va_list args;
  522. X  extern int errno;
  523. X  int save_errno;
  524. X
  525. X  save_errno = errno;
  526. X  fprintf (stderr, "%s: ", program_name);
  527. X  va_start (args);
  528. X  vfprintf (stderr, str, args);
  529. X  va_end (args);
  530. X  fprintf (stderr, ": %s\n", strerror (save_errno));
  531. X  exit (1);
  532. X}
  533. X
  534. X/* Open `path' for reading as a mode 0600 FIFO, creating it if necessary.
  535. X   Return the file descriptor. */
  536. X
  537. Xint
  538. Xopen_fifo (path)
  539. X     char *path;
  540. X{
  541. X  int fifd;
  542. X
  543. X  if (mknod (path, 010600, 0) == -1 && errno != EEXIST)
  544. X    msg_perror_fatal ("Cannot create FIFO %s", path);
  545. X  if (chmod (path, 0600))
  546. X    msg_perror_fatal ("Cannot change mode of FIFO %s", path);
  547. X  while ((fifd = open (path, O_RDONLY | O_TRUNC)) == -1 && errno == EINTR)
  548. X     /* Do nothing. */ ;
  549. X  if (fifd == -1)
  550. X    msg_perror_fatal ("Cannot open FIFO %s for reading", path);
  551. X  return fifd;
  552. X}
  553. X
  554. X/* Return nonzero if there is another process already reading `fifo'.
  555. X   If there isn't, open will fail with EPIPE (write on broken pipe). */
  556. X
  557. Xint
  558. Xdaemon_running (fifo)
  559. X     char *fifo;
  560. X{
  561. X  int fifd;
  562. X
  563. X  fifd = open (fifo, O_WRONLY | O_NDELAY);
  564. X  if (fifd == -1)
  565. X    return 0;
  566. X  else
  567. X    {
  568. X      close (fifd);
  569. X      return 1;
  570. X    }
  571. X}
  572. END_OF_FILE
  573. if test 11659 -ne `wc -c <'comsat.c'`; then
  574.     echo shar: \"'comsat.c'\" unpacked with wrong size!
  575. fi
  576. # end of 'comsat.c'
  577. fi
  578. if test -f 'biff.c' -a "${1}" != "-c" ; then 
  579.   echo shar: Will not clobber existing file \"'biff.c'\"
  580. else
  581. echo shar: Extracting \"'biff.c'\" \(2171 characters\)
  582. sed "s/^X//" >'biff.c' <<'END_OF_FILE'
  583. X/* biff - accept or refuse new mail messages from comsat
  584. X
  585. X   Usage: biff [yn]
  586. X
  587. X   David MacKenzie
  588. X   public domain
  589. X   Latest revision: 08/19/89 */
  590. X
  591. X#include <stdio.h>
  592. X#include <sys/types.h>
  593. X#include <sys/stat.h>
  594. X#include <varargs.h>
  595. X
  596. Xchar *ttyname ();
  597. X
  598. Xchar *any_ttyname ();
  599. Xvoid msg_perror_fatal ();
  600. Xvoid usage ();
  601. X
  602. Xchar *program_name;
  603. X
  604. Xint
  605. Xmain (argc, argv)
  606. X     int argc;
  607. X     char **argv;
  608. X{
  609. X  struct stat stats;
  610. X  char *tty;
  611. X
  612. X  program_name = argv[0];
  613. X  tty = any_ttyname ();
  614. X  if (tty == NULL)
  615. X    {
  616. X      fprintf (stderr, "%s: Not connected to a terminal\n", argv[0]);
  617. X      exit (1);
  618. X    }
  619. X  if (stat (tty, &stats) == -1)
  620. X    msg_perror_fatal ("Cannot stat %s", tty);
  621. X  switch (argc)
  622. X    {
  623. X    case 1:
  624. X      printf ("is %c\n", (stats.st_mode & S_IEXEC) ? 'y' : 'n');
  625. X      break;
  626. X    case 2:
  627. X      if (*argv[1] == '-')
  628. X    ++argv[1];        /* Allow '-y' or 'y'. */
  629. X      switch (*argv[1])
  630. X    {
  631. X    case 'y':
  632. X      if (chmod (tty, stats.st_mode | S_IEXEC) == -1)
  633. X        msg_perror_fatal ("Cannot change mode of %s", tty);
  634. X      break;
  635. X    case 'n':
  636. X      if (chmod (tty, stats.st_mode & ~S_IEXEC) == -1)
  637. X        msg_perror_fatal ("Cannot change mode of %s", tty);
  638. X      break;
  639. X    default:
  640. X      usage ();
  641. X    }
  642. X      break;
  643. X    default:
  644. X      usage ();
  645. X    }
  646. X  exit (0);
  647. X  /* NOTREACHED */
  648. X}
  649. X
  650. Xchar *
  651. Xany_ttyname ()
  652. X{
  653. X  char *tty;
  654. X
  655. X  tty = ttyname (2);
  656. X  if (tty)
  657. X    return tty;
  658. X  tty = ttyname (1);
  659. X  if (tty)
  660. X    return tty;
  661. X  tty = ttyname (0);
  662. X  if (tty)
  663. X    return tty;
  664. X  return NULL;
  665. X}
  666. X
  667. X/* ANSI C function. */
  668. X
  669. Xchar *
  670. Xstrerror (n)
  671. X     int n;
  672. X{
  673. X  extern char *sys_errlist[];
  674. X  extern int sys_nerr;
  675. X
  676. X  return n >= 0 && n < sys_nerr ? sys_errlist[n] : "Unknown error";
  677. X}
  678. X
  679. X/* Print "program_name: str_and_optional_args: perror_message" on stderr,
  680. X   then exit with error status. */
  681. X/* VARARGS */
  682. Xvoid
  683. Xmsg_perror_fatal (str, va_alist)
  684. X     char *str;
  685. X     va_dcl
  686. X{
  687. X  va_list args;
  688. X  extern int errno;
  689. X  int save_errno;
  690. X
  691. X  save_errno = errno;
  692. X  fprintf (stderr, "%s: ", program_name);
  693. X  va_start (args);
  694. X  vfprintf (stderr, str, args);
  695. X  va_end (args);
  696. X  fprintf (stderr, ": %s\n", strerror (save_errno));
  697. X  exit (1);
  698. X}
  699. X
  700. Xvoid
  701. Xusage ()
  702. X{
  703. X  fprintf (stderr, "Usage: %s [yn]\n", program_name);
  704. X  exit (1);
  705. X}
  706. END_OF_FILE
  707. if test 2171 -ne `wc -c <'biff.c'`; then
  708.     echo shar: \"'biff.c'\" unpacked with wrong size!
  709. fi
  710. # end of 'biff.c'
  711. fi
  712. if test -f 'lmail.diffs' -a "${1}" != "-c" ; then 
  713.   echo shar: Will not clobber existing file \"'lmail.diffs'\"
  714. else
  715. echo shar: Extracting \"'lmail.diffs'\" \(1782 characters\)
  716. sed "s/^X//" >'lmail.diffs' <<'END_OF_FILE'
  717. X*** lmail.c.dist    Tue Aug 15 03:34:47 1989
  718. X--- lmail.c    Wed Aug 16 02:30:06 1989
  719. X***************
  720. X*** 527,532 ****
  721. X--- 527,533 ----
  722. X                          return(8);
  723. X                      }
  724. X                  } else {
  725. X+                     long where = -1, ftell ();
  726. X                      setgid(MAILGID);
  727. X                      setuid(pwd_mailman->pw_uid);    /* give up root uid */
  728. X                      sprintf(temp, "%s%s", MAIL_DIR, dest);
  729. X***************
  730. X*** 535,542 ****
  731. X                      if ((outfile = fopen(temp, "a")) == NULL) {
  732. X                          (void) fprintf(stderr, "** Can't open user mail file %s\n", temp);
  733. X                          status = 5;
  734. X!                     } else
  735. X                          copy(outfile, in_fd, author);
  736. X                      chown(temp, (int)pwd->pw_uid, MAILGID);
  737. X                      if (fclose(outfile)) {
  738. X                          (void) fprintf(stderr, "** Could not close mail file %s\n", temp);
  739. X--- 536,545 ----
  740. X                      if ((outfile = fopen(temp, "a")) == NULL) {
  741. X                          (void) fprintf(stderr, "** Can't open user mail file %s\n", temp);
  742. X                          status = 5;
  743. X!                     } else {
  744. X!                         where = ftell(outfile);
  745. X                          copy(outfile, in_fd, author);
  746. X+                     }
  747. X                      chown(temp, (int)pwd->pw_uid, MAILGID);
  748. X                      if (fclose(outfile)) {
  749. X                          (void) fprintf(stderr, "** Could not close mail file %s\n", temp);
  750. X***************
  751. X*** 543,548 ****
  752. X--- 546,553 ----
  753. X                          status = 7;
  754. X                      }
  755. X                      unlock(temp);
  756. X+                     if (where != -1)
  757. X+                         biff(dest, where);
  758. X                      _exit(status);
  759. X                  }
  760. X              }
  761. X***************
  762. X*** 626,629 ****
  763. X--- 631,651 ----
  764. X      return;
  765. X  }
  766. X  
  767. X+ #include <fcntl.h>
  768. X+ 
  769. X+ /* Do our best to biff the recipient.  Errors don't bother us. */
  770. X  
  771. X+ biff (user, offset)
  772. X+      char *user;
  773. X+      long offset;
  774. X+ {
  775. X+   int fd;
  776. X+   char biffbuf[30];
  777. X+ 
  778. X+   fd = open ("/etc/comsat.fifo", O_WRONLY | O_NDELAY);
  779. X+   if (fd == -1)
  780. X+     return;
  781. X+   sprintf (biffbuf, "%s@%ld\n", user, offset);
  782. X+   write (fd, biffbuf, strlen (biffbuf));
  783. X+   close (fd);
  784. X+ }
  785. END_OF_FILE
  786. if test 1782 -ne `wc -c <'lmail.diffs'`; then
  787.     echo shar: \"'lmail.diffs'\" unpacked with wrong size!
  788. fi
  789. # end of 'lmail.diffs'
  790. fi
  791. if test -f 'mailwrap.c' -a "${1}" != "-c" ; then 
  792.   echo shar: Will not clobber existing file \"'mailwrap.c'\"
  793. else
  794. echo shar: Extracting \"'mailwrap.c'\" \(1624 characters\)
  795. sed "s/^X//" >'mailwrap.c' <<'END_OF_FILE'
  796. X/* Local Mail Interceptor to handle interface to comsat */
  797. X/* Args for local mail are  [ -r sender ] parties ... */
  798. X/* Jim Mattson <mattson%cs@ucsd.edu> */
  799. X
  800. X#include <sys/types.h>
  801. X#include <sys/stat.h>
  802. X#include <fcntl.h>
  803. X#include <stdio.h>
  804. X
  805. X#define FIFO "/usr/tmp/comsat.fifo"
  806. X#define MAILDIR "/usr/spool/mail"
  807. X#define MAILER "/usr/lib/mail/mail.orig"
  808. X
  809. Xmain(argc, argv)
  810. Xint argc;
  811. Xchar **argv;
  812. X{
  813. X    off_t *offsets;        /* Mailbox offsets before delivery */
  814. X    struct stat stbuf;    /* For stat'ing mailboxes */
  815. X    char **av = argv;    /* Old argv */
  816. X    int fd;            /* file descriptor for FIFO */
  817. X    FILE *fp;        /* File pointer for FIFO */
  818. X    int rc;            /* Return Code from local mailer */
  819. X    int i;
  820. X
  821. X    /* Get rid of program name and [ -r sender ] */
  822. X    argc--;
  823. X    argv++;
  824. X    if(!strcmp(argv[0], "-r")) {
  825. X        argc -= 2;
  826. X        argv += 2;
  827. X    }
  828. X    if(argc == 0)
  829. X        exit(0);
  830. X
  831. X    if((offsets = (off_t *)malloc(sizeof(off_t) * argc)) == NULL)
  832. X        bailout(av);
  833. X
  834. X    /* Get mailbox offsets */
  835. X    if(chdir(MAILDIR) < 0)
  836. X        bailout(av);
  837. X    for(i = 0; i < argc; i++) {
  838. X        if(stat(argv[i], &stbuf) < 0)
  839. X            offsets[i] = 0;
  840. X        else
  841. X            offsets[i] = stbuf.st_size;
  842. X    }
  843. X
  844. X    /* Send mail and wait for exit code */
  845. X    switch(fork()) {
  846. X    case -1:
  847. X    case 0:
  848. X        bailout(av);    /* No return */
  849. X    default:
  850. X        wait(&rc);
  851. X    }
  852. X    /* Send messages to comsat if it's listening */
  853. X    if((fd = open(FIFO, O_WRONLY | O_NDELAY)) >= 0) {
  854. X        if((fp = fdopen(fd, "w")) != NULL) {
  855. X            for(i = 0; i < argc; i++)
  856. X                fprintf(fp, "%s@%d\n", argv[i], offsets[i]);
  857. X            fclose(fp);
  858. X        }
  859. X        close(fd);
  860. X    }
  861. X    /* Exit with local mailer's return code */
  862. X    exit(rc >> 8);
  863. X}
  864. X
  865. Xbailout(argv)
  866. Xchar **argv;
  867. X{
  868. X    argv[0] = MAILER;
  869. X    execv(MAILER, argv);
  870. X    _exit(0);
  871. X}
  872. END_OF_FILE
  873. if test 1624 -ne `wc -c <'mailwrap.c'`; then
  874.     echo shar: \"'mailwrap.c'\" unpacked with wrong size!
  875. fi
  876. # end of 'mailwrap.c'
  877. fi
  878. echo shar: End of shell archive.
  879. exit 0
  880.  
  881.